package weaver.limitCurrent;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.ProxoolFacade;
import weaver.general.GCONST;
import weaver.monitor.monitor.MemMonitor;

public class LimitCurrentService {
    public static ConcurrentHashMap<String, AtomicInteger> countmap = new ConcurrentHashMap<String, AtomicInteger>();

    private static int conncount = Integer.valueOf(LimitMap.get("conncount",
            "50")).intValue();

    private static int httpcount = Integer.valueOf(LimitMap.get("httpcount",
            "20")).intValue();

    private static int overtime = Integer.valueOf(LimitMap.get("overtime",
            "5000000")).intValue();

    public static int sleepcount = Integer.valueOf(LimitMap.get("sleepcount",
            "50")).intValue();

    public static ConcurrentHashMap<String, ConcurrentSkipListMap<String, Long>> cacheMap = new ConcurrentHashMap<String, ConcurrentSkipListMap<String, Long>>();

    public static String getCountMap() {
        int i = 1;
        StringBuilder sb = new StringBuilder();
        for (AtomicInteger value : countmap.values()) {
            sb.append(i).append("��ʵʱ������").append(value.intValue())
                    .append("<br/>");
            i++;
        }
        return sb.toString();
    }

    public static String getCacheMap() {
        StringBuilder sb = new StringBuilder();
        int j = 1;
        for (ConcurrentSkipListMap<String, Long> value : cacheMap.values()) {
            int i = 0;
            for (Long value2 : value.values()) {
                if (System.nanoTime() - value2.longValue() > overtime)
                    i++;
            }
            if (i >= httpcount) {
                sb.append(j).append(":实时数量:").append(i).append("<br/>");
                j++;
            }
        }
        return sb.toString();
    }

    public static boolean isLimit(String uri) {
        if (MemMonitor.gcMemWarnFlag)
            return false;
        AtomicInteger value = countmap.get(uri);
        if (value != null && value.intValue() > httpcount) {
            int activeconnCount = 0;
            try {
                activeconnCount = ProxoolFacade.getSnapshot(
                        GCONST.getServerName()).getActiveConnectionCount();
            } catch (ProxoolException e) {
                e.printStackTrace();
            }
            if (activeconnCount > conncount && isOverTime(uri))
                return true;
        }
        return false;
    }


    public static void putRequestCount(String uri) {
        AtomicInteger value = countmap.get(uri);
        if (value == null) {
            value = new AtomicInteger(1);
            countmap.put(uri, value);
        } else {
            value.incrementAndGet();
        }
    }

    public static void removeRequestCount(String uri) {
        AtomicInteger value = countmap.get(uri);
        if (value == null)
            return;
        value.decrementAndGet();
    }

    private static boolean isOverTime(String uri) {
        ConcurrentSkipListMap<String, Long> timeMap = cacheMap.get(uri);
        if (timeMap != null && timeMap.size() >= httpcount) {
            int overTimeCount = 0;
            long overTimeTotal = 0L;
            int loopCount = 0;
            for (Long m : timeMap.values()) {
                loopCount++;
                long overTime = System.nanoTime() - m.longValue();
                overTimeTotal += overTime;
                if (overTime > overtime)
                    overTimeCount++;
                if (loopCount >= httpcount)
                    break;
            }
            long averageOverTime = overTimeTotal / httpcount;
            boolean averageOverTimeIsOver = (averageOverTime > overtime);
            boolean overTimeCountIsOver = (overTimeCount > httpcount / 2);
            if (averageOverTimeIsOver && overTimeCountIsOver)
                return true;
        }
        return false;
    }

    public static void putRequestBean(String uri, String uritime, long time) {
        ConcurrentSkipListMap<String, Long> timeMap = cacheMap.get(uri);
        if (timeMap == null) {
            timeMap = new ConcurrentSkipListMap<String, Long>();
            timeMap.put(uritime, Long.valueOf(time));
            cacheMap.put(uri, timeMap);
        } else {
            timeMap.put(uritime, Long.valueOf(time));
        }
    }

    public static void removeRequestBean(String uri, String uritime) {
        ConcurrentSkipListMap<String, Long> timeMap = cacheMap.get(uri);
        if (timeMap == null)
            return;
        timeMap.remove(uritime);
    }
}
